package executor

import (
	"smart-flow/server/config"
	"sync"
	"time"

	cmap "github.com/orcaman/concurrent-map"
)

var (
	failureCtOnce sync.Once
	failureCmOnce sync.Once
	failureCuOnce sync.Once
	failureCt     *Failure
	failureCm     *Failure
	failureCu     *Failure
)

type Failure struct {
	losers cmap.ConcurrentMap
}

func FailureInstance(isp string) *Failure {
	switch isp {
	case config.IspTelecom:
		failureCtOnce.Do(func() {
			failureCt = &Failure{
				losers: cmap.New(),
			}
		})
		return failureCt
	case config.IspMobile:
		failureCmOnce.Do(func() {
			failureCm = &Failure{
				losers: cmap.New(),
			}
		})
		return failureCm
	default:
		failureCuOnce.Do(func() {
			failureCu = &Failure{
				losers: cmap.New(),
			}
		})
		return failureCu
	}
}

func (f *Failure) AddLoser(uid string, timestamp int64) {
	f.losers.Set(uid, timestamp)
}

func (f *Failure) GetLoser(uid string) int64 {
	val, exist := f.losers.Get(uid)
	if !exist {
		return 0
	}
	return val.(int64)
}

func (f *Failure) DelLoser(uid string) {
	f.losers.Remove(uid)
}

func (f *Failure) ExistLoser(uid string) bool {
	return f.losers.Has(uid)
}

func (f *Failure) Count() int {
	return f.losers.Count()
}

func (f *Failure) Check(uid string) {
	timestamp := f.GetLoser(uid)
	if timestamp == 0 {
		return
	}
	if time.Now().Unix()-timestamp > config.LoserDuration {
		f.DelLoser(uid)
	}
}
